﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Pong_Project.Game_objects;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Pong_Project
{
    class GameObjectManager
    {
        private Bat batLeft, batRight;
        private Ball ball;
        private PowerupBat ballTurnsFromYou, ballTurnAgainstYou;
        private PowerupBall biggerBat, increaseBatSpeed, reverseBatKeys, decreaseBatSpeed, smallerBat, goldenBallPowerup;
        private static List<GameObject> activeGameObjects = new List<GameObject>();
        private static List<Obstacle> gameObstacles = new List<Obstacle>();
        private PowerupManager powerupManager;
        private CollisionDetector collisionDetector;
        private static bool spritesLoaded = false;
        private static List<Powerup> powerupList = new List<Powerup>();

        public GameObjectManager()
        {
            ball = AbstractFactory.Ball;
            batLeft = AbstractFactory.BatLeft;
            batRight = AbstractFactory.BatRight;

            //AbstractFactory.abstractFactory(kind, collectorIsBall,collectorIsBat, affectsBat, affectsBall, GameObjectIdentity.PowerupOppositeBallDirection, objectThatCanPickItUp, timeToLast, timeToLive,  minTimeBeforeSpawning, maxTimeBeforeSpawning, scaleFactor,directionModifyer);

            //PowerupBall
            biggerBat = (PowerupBall)AbstractFactory.abstractFactory("powerup", null, ball, batLeft, null, GameObjectIdentity.PowerupBallBiggerBat, 500, 800, 600, 800, 1.5f, new Vector2(0, 0));
            increaseBatSpeed = (PowerupBall)AbstractFactory.abstractFactory("powerup", null, ball, batLeft, null, GameObjectIdentity.PowerupBallIncreaseBatSpeed, 400, 700, 1000, 1300, 0.0f, new Vector2(0, 1.5f));
            goldenBallPowerup = (PowerupBall)AbstractFactory.abstractFactory("powerup", null, ball, batLeft, null, GameObjectIdentity.PowerupBallGoldenBallPowerup, 0, 500, 2200, 2200, 0, new Vector2(666, 666));

            //Powerdown
            reverseBatKeys = (PowerupBall)AbstractFactory.abstractFactory("powerup", null, ball, batLeft, null, GameObjectIdentity.PowerupBallReverseBatKeys, 300, 700, 1200, 1500, 0.0f, new Vector2(0, -1));
            decreaseBatSpeed = (PowerupBall)AbstractFactory.abstractFactory("powerup", null, ball, batLeft, null, GameObjectIdentity.PowerupBallDecreaseBatSpeed, 300, 1500, 1100, 1500, 0, new Vector2(0, 0.4f));
            smallerBat = (PowerupBall)AbstractFactory.abstractFactory("powerup", null, ball, batLeft, null, GameObjectIdentity.PowerupBallSmallerBat, 400, 600, 900, 1200, 0.5f, new Vector2(0, 0));

            //PowerupBat
            ballTurnsFromYou = (PowerupBat)AbstractFactory.abstractFactory("powerup", batLeft, null, null, ball, GameObjectIdentity.PowerupOppositeBallDirection, 0, 500, 300, 600, 0, new Vector2(-2, 1));
            ballTurnAgainstYou = (PowerupBat)AbstractFactory.abstractFactory("powerup", batLeft, null, null, ball, GameObjectIdentity.PowerupBatBallTurnAgainstYou, 0, 400, 1300, 1700, 0, new Vector2(2, 1));

            //add all the active gameobject to list
            activeGameObjects.Add(ball);
            activeGameObjects.Add(batLeft);
            activeGameObjects.Add(batRight);


            /////////////////////////////////////////////////////////////////////7
            //Do not change this order!!!!
            //////////////////////////////////////////////////////////////////////

            powerupList.Add(biggerBat);

            powerupList.Add(ballTurnsFromYou);

            powerupList.Add(increaseBatSpeed);

            powerupList.Add(decreaseBatSpeed);

            powerupList.Add(reverseBatKeys);

            powerupList.Add(smallerBat);

            powerupList.Add(ballTurnAgainstYou);

            powerupList.Add(goldenBallPowerup);


            //////////////////////////////////////////////////////////////////////////

            ///////////////////////////////////////////////////////////////////////////

            powerupManager = new PowerupManager(batLeft, batRight, ball);
            collisionDetector = new CollisionDetector(batLeft, batRight, ball);
            ball.RegisterObserver(collisionDetector);
        }

        public static bool SpritesLoaded
        {
            get { return spritesLoaded; }
        }

        public void LoadContent(ContentManager content)
        {
            spritesLoaded = true;

            batLeft.Sprite = content.Load<Texture2D>("Bat");
            batRight.Sprite = content.Load<Texture2D>("Bat");
            ball.Sprite = content.Load<Texture2D>("Ball2");

            biggerBat.Sprite = content.Load<Texture2D>("PU_BiggerBat");
            ballTurnsFromYou.Sprite = content.Load<Texture2D>("PU_BallTurnsFromYou");
            increaseBatSpeed.Sprite = content.Load<Texture2D>("PU_IncreaseBatSpeed");
            decreaseBatSpeed.Sprite = content.Load<Texture2D>("PU_DecreaseBatSpeed");
            reverseBatKeys.Sprite = content.Load<Texture2D>("PU_ReverseBatKeys");
            smallerBat.Sprite = content.Load<Texture2D>("PU_SmallerBat");
            ballTurnAgainstYou.Sprite = content.Load<Texture2D>("PU_BallTurnsAgainstYou");
            goldenBallPowerup.Sprite = content.Load<Texture2D>("PU_GoldenBallPowerup");

            foreach (Obstacle obstacle in gameObstacles)
            {
                obstacle.Sprite = content.Load<Texture2D>("Obstacle");
            }
        }


        public void Update(GameTime gameTime)
        {
            powerupManager.Update(gameTime);
            collisionDetector.Update(gameTime);
            //ball.NotifyObservers(gameTime);

            foreach (GameObject g in activeGameObjects)
            {
                g.Update(gameTime);
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (GameObject g in activeGameObjects)
            {
                g.Draw(spriteBatch);
            }
        }



        public static void AddObstacle(Obstacle obstacle)
        {
            gameObstacles.Add(obstacle);
        }

        // A static method for resetting all the game objects
        public static void ResetObjects()
        {
            foreach (GameObject g in activeGameObjects)
            {
                g.Reset();
            }
        }

        // A static list of all the GameObjects in the game
        public static void AddGameObject(GameObject gameObject)
        {
            activeGameObjects.Add(gameObject);
        }


        // Returns the GameObject with the specified identity, or null if it's not found
        public static GameObject GetGameObject(GameObjectIdentity identity)
        {
            foreach (GameObject g in activeGameObjects)
            {
                if (g.Identity == identity)
                    return g;
            }
            return null;
        }

        private static bool IsObstacle(GameObject gameObject)
        {
            return gameObject.Identity == GameObjectIdentity.Obstacle;
        }

        public static void ReplaceAllObstacles(List<Obstacle> obstacles)
        {
            activeGameObjects.RemoveAll(IsObstacle);
            activeGameObjects.AddRange(obstacles);
        }

        public static void ChosenPowerups(List<bool> choosenPowerups)
        {

            /////////////////////////
            //Checs if the powerup is chosen in the settings, of not they are remved from the activeGameObjects list
            /////////////////////////
            for (int i = 0; i < powerupList.Count; i++)
            {
                if (choosenPowerups[i] == true)
                {
                    bool isthere = false;
                    for (int j = 0; j < activeGameObjects.Count; j++)
                    {
                        if (powerupList[i].Identity == activeGameObjects[j].Identity)
                            isthere = true;
                    }
                    if (isthere == false)
                        activeGameObjects.Add(powerupList[i]);

                }
                else
                {
                    for (int j = 0; j < activeGameObjects.Count; j++)
                    {
                        if (powerupList[i].Identity == activeGameObjects[j].Identity)
                        {
                            GameObjectManager.activeGameObjects.Remove(activeGameObjects[j]);
                            break;
                        }
                    }
                }
            }
        }
    }
}
